﻿using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace GPExplorer {
    /// <summary>
    /// A representation of a Guitar Pro File header.
    /// </summary>
    [Serializable()]
    public class GpFile {
        //This is the split strings array counter. Its set to 1 to skip the first array element, which is always a version number
        private int _k;

        /// <summary>
        /// Gets the Guitar Pro file.
        /// </summary>
        /// <param name="filepath">The file path.</param>
        /// <param name="gpFile">The GPFile object.</param>
        /// <returns>A completed GP File</returns>
        public GpFile GetGpFile(string filepath, GpFile gpFile) {
            FilePath = filepath;
                return ParseSong(gpFile);
        }

        /// <summary>
        /// Parses the song that is in GP format.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <returns></returns>
        private GpFile ParseSong(GpFile file) {

            try{
                using (StreamReader _sr = new StreamReader(FilePath, Encoding.Default)){
                    char[] _buffer = new char[1024];

                    //Guitar Pro file header
                    _sr.Read(_buffer, 0, 32);
                    
                    _sr.Read(_buffer,0,200);
                    string _stuff = new string(_buffer);
                    
                    string[] _test = _stuff.Split(new[] { "\0\0\0" }, StringSplitOptions.RemoveEmptyEntries);
                   
                    //Title
                    string _name = ParseFile(_test, _k);

                    //Skip the Subtitle
                    _k+=2;

                    //Artist
                    string _artist = ParseFile(_test, _k);

                    //Clean string of single "'" character
                    string _fp = FilePath.Replace("'", "''");
                    FilePath = _fp;

                    //Song
                    file.SongName = new string(_name.Where(c => !char.IsControl(c)).ToArray());
                    string _song = file.SongName.Replace("'", "''"); 
                    file.SongName = _song;
                    
                    //Artist
                    file.Artist = new string(_artist.Where(c => !char.IsControl(c)).ToArray());
                    string _art = file.Artist.Replace("'", "''");
                    file.Artist = _art.Trim();

                    //File date
                    FileInfo _fileInfo = new FileInfo(FilePath);
                    file.FileDate = _fileInfo.LastWriteTime.ToShortDateString();

                    //Version
                    file.Version = Path.GetExtension(FilePath).Replace(".",string.Empty);
                }
            }
            catch (Exception _e) {
                MessageBox.Show(_e.Message);
                return null;
            }
            return file;
        }

        /// <summary>
        /// Parses the file.
        /// </summary>
        /// <param name="test">The split string.</param>
        /// <param name="k">The current counter.</param>
        /// <returns>A string containing the desired GPFile entry</returns>
        private string ParseFile(string[] test, int k) {
            bool _flag = false;
            string _name = string.Empty;
            int _i;
            //Assign i to the k counter so that we don't always start at the beginning and get the same string
            for (_i = k; _i < test.Length; _i++) {
                for (int _j = 0; _j < test[_i].Length; _j++) {
                    if (char.IsControl(test[_i][_j])) {
                    }
                    else {//This contains a real string. Get out and return
                        _flag = true;
                        break;
                    }
                }
                if (_flag) {
                    break;
                }
            }
            if (_flag) {
                _k = _i;
                _name = test[_i].Substring(1);
            }
            return _name;
        }



        /// <summary>
        /// Gets or sets the file path.
        /// </summary>
        /// <value>
        /// The file path.
        /// </value>
        public string FilePath { get; set; }
        /// <summary>
        /// Gets or sets the name of the song.
        /// </summary>
        /// <value>
        /// The name of the song.
        /// </value>
        public string SongName { get; set; }
        /// <summary>
        /// Gets or sets the artist.
        /// </summary>
        /// <value>
        /// The artist.
        /// </value>
        public string Artist { get; set; }
        /// <summary>
        /// Gets or sets the Guitar Pro version.
        /// </summary>
        /// <value>
        /// The version.
        /// </value>
        public string Version { get; set; }
        /// <summary>
        /// Gets or sets the file date.
        /// </summary>
        /// <value>
        /// The file date.
        /// </value>
        public string FileDate { get; set; }
    }
}
